import router, { tabBars } from '@/router'
import { nanoid } from 'nanoid'
import type { RouteLocationNormalizedGeneric, RouteLocationRaw } from 'vue-router'
import EventChannel from 'async-event-channel'

// 路由栈项类型
export type RoutesHistoryItem = RouteLocationNormalizedGeneric & {
  __id: string
  __eventChannel: EventChannel
}
// 路由栈
export const routesHistory = shallowReactive<RoutesHistoryItem[]>([])
// 当前跳转方式
export const currentTransition = ref<{
  toPath: string
  fromPath: string
  type: 'init' | 'push' | 'replace' | 'back'
} | null>(null)

// tabBars 路由附加信息
export const routesHistoryOther_tabBars = new Map(
  tabBars.map((item) => [
    item.path,
    {
      __id: item.path,
      __eventChannel: new EventChannel(),
    },
  ]),
)

// 创建路由栈项
const createHistory = (to: RouteLocationNormalizedGeneric) =>
  Object.assign(
    to,
    routesHistoryOther_tabBars.get(to.path) || {
      __id: `${to.fullPath}::${nanoid()}`,
      __eventChannel: new EventChannel(),
    },
  )

// 监听路由变化-浏览器前进后退
let back = 0
router.options.history.listen((_to, _from, { delta, direction }) => {
  if (direction !== 'back') return
  back = delta
})

// 返回前一个页面时重定向到指定页面
export const backRedirect = ref<RouteLocationRaw | null>(null)
router.afterEach(() => {
  if (backRedirect.value && back) {
    const redirect = backRedirect.value
    backRedirect.value = null
    router.replace(redirect)
  }
})

// 监听路由变化-路由跳转
router.afterEach((to, from) => {
  if (to.fullPath === from.fullPath) return
  let type: NonNullable<typeof currentTransition.value>['type'] = 'init'
  // replace
  if (history.state.scroll === false) {
    type = 'replace'
    routesHistory[routesHistory.length - 1] = createHistory(to)
  }
  // back
  else if (back) {
    type = 'back'
    if (routesHistory.length === 1) {
      routesHistory[0] = createHistory(to)
    } else {
      routesHistory.splice(back)
    }
    back = 0
  }
  // forward/push
  else {
    type = routesHistory.length ? 'push' : 'init'
    routesHistory.push(createHistory(to))
  }
  currentTransition.value = {
    toPath: to.path,
    fromPath: from.path,
    type,
  }
})
